//
// Created by HP on 2022/3/9.
//

#ifndef FONTRENDER_RENDERMATH_H
#define FONTRENDER_RENDERMATH_H

#include "vertex.h"

// 二阶 Bezier 曲线表达式:
// P(t) = (1-t)^2 * P0 + 2t(1-t) * P1 + t^2 * P2 --- 1
// 化简得:
// P(t) = t^2 * (P0 - 2P1 + P2) + t * (2P1 - P0) + P0 --- 2
// 其中 P1 为控制点, P0 为起点, P2 为终点
//
// 二阶 Bezier 曲线的均匀离散化:
// 为了在均匀 Bezier 曲线上均匀采样, 我们可以将 Bezier 曲线理解为一条运动轨迹, 则:
// Px(t) = t^2 * (P0.x - 2P1.x + P2.x) + t * (2P1.x - P0.x) + P0.x --- 3
// Py(t) = t^2 * (P0.y - 2P1.y + P2.y) + t * (2P1.y - P0.y) + P0.y --- 4
//               |-------- a --------|       |----- b ----|
// 上面 3、4 式分别表示在 x轴 和 y轴 上的位移, 分别求导:
// Px'(t) = 2t * a.x + b.x  --- 5
// Py'(t) = 2t * a.y + b.y  --- 6
// 则 5、6 式表示 x轴 和 y轴 上的瞬时速度(速率), 故合速率为:
// V(t) = sqrt( Px'(t)^2 + Py'(t)^2 )
//      = sqrt( t^2 * 4((a.x)^2 + (a.y)^2) + (b.x)^2 + (b.y)^2 + t * 4(a.x * b.x + a.y * b.y) )
//      = sqrt( A * t^2 + B * t + C)
// 其中 A = 4((a.x)^2 + (a.y)^2),
//     B = 4(a.x * b.x + a.y * b.y)
//     C = (b.x)^2 + (b.y)^2
// 在得到 V(t) 后, 认为在之后的 dt 时间内, 物体作匀速直线运动
// 并在算法的开始时, 计算 Bezier 曲线的总弧长 L, 把弧长分成 n 分, 每一个 dt 时间内走 L / n 长, 从而得到 t
// 而弧长的积分是没有解析解的
// 可以使用 Simpson's 3/8 rule 对其逼近

// 参照 https://zhuanlan.zhihu.com/p/53492083


typedef struct {
    Vertex p0;
    Vertex p1;
    Vertex p2;
} BezierQuadratic;

/**
 * norm(P'(t))
 * @param curve
 * @param t
 * @return
 */
double bezier_quadratic_dev(BezierQuadratic *curve, double t);

/**
 * Simpson's 3/8 rule
 * @param curve
 * @param L
 * @param R
 * @return
 */
double simpson(BezierQuadratic *curve, double l, double r);

/**
 * 计算积分
 * @param curve
 * @param l
 * @param r
 * @param eps 期望容差
 * @return
 */
double bezier_len(BezierQuadratic *curve, double l, double r, double eps);

void generate(BezierQuadratic *curve, Vertex *vertices, int cnt);

#endif //FONTRENDER_RENDERMATH_H
